package edu.stanford.bmir.protege.web.client.ui.ontology.stkos.common.treepanel;

import java.util.List;
import java.util.Set;

import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.web.bindery.event.shared.Event.Type;
import com.gwtext.client.widgets.tree.TreeNode;

import edu.stanford.bmir.protege.web.client.project.Project;
import edu.stanford.bmir.protege.web.client.rpc.OntologyServiceManager;
import edu.stanford.bmir.protege.web.client.rpc.data.EntityData;
import edu.stanford.bmir.protege.web.client.rpc.data.SubclassEntityData;
import edu.stanford.bmir.protege.web.client.ui.ontology.stkos.common.GWTExtUtil;
import edu.stanford.bmir.protege.web.client.ui.util.UIUtil;
import edu.stanford.bmir.protege.web.shared.event.ClassFrameChangedEvent;
import edu.stanford.bmir.protege.web.shared.event.ClassFrameChangedEventHandler;
import edu.stanford.bmir.protege.web.shared.project.ProjectId;
import edu.stanford.bmir.protege.web.shared.watches.EntityFrameWatch;
import edu.stanford.bmir.protege.web.shared.watches.Watch;

/**
 * Stkos Class Tree Panel
 * 
 * @author LWS
 * 
 */
@SuppressWarnings("unchecked")
public class StkosClassTreePanel extends AbstractStkosTreePanel {

	private static final String SUFFIX_ID_LOCAL_ANNOTATION_IMG = "_locAnnImg";

	private static final String SUFFIX_ID_LOCAL_ANNOTATION_COUNT = "_locAnnCnt";

	protected static final String WATCH_ICON_STYLE_STRING = "style=\"position:relative; top:3px; left:2px;\"";

	public StkosClassTreePanel(Project project) {
		super(project);
	}

	@Override
	protected void registerProjectEventHandler() {
	}
	
	protected void registerProjectEventHandler2222() {
		ProjectId projectId = getProject().getProjectId();

		Type<ClassFrameChangedEventHandler> type = ClassFrameChangedEvent.TYPE;

		ClassFrameChangedEventHandler handler = new ClassFrameChangedEventHandler() {
			@Override
			public void classFrameChanged(ClassFrameChangedEvent event) {
				if (event == null || event.getEntity() == null
						|| event.getEntity().getIRI() == null) {
					return;
				}
				try {
					TreeNode node = (TreeNode) getNodeById(event.getEntity()
							.getIRI().toString());

					refreshTreeNode(node);
				} catch (Exception e) {
					GWT.log("Update tree node text error.", e);
				}
			}
		};

		AbstractStkosTreePanel.manager.registerHandlerToProject(projectId,
				type, handler);
	}

	@Override
	protected void setRootNodeChild() {
		if (getProject() != null && getProject().getProjectId() != null) {
			final String failMsg = "Loading Project ["
					+ getProject().getDisplayName() + "] RootEntity Failure!";
			OntologyServiceManager.getInstance().getRootEntity(
					getProject().getProjectId(),
					new AsyncCallback<EntityData>() {

						@Override
						public void onFailure(Throwable caught) {
							GWT.log(failMsg, caught);
							createClassRootNodeChild(null);
						}

						@Override
						public void onSuccess(final EntityData result) {
							if (result == null) {
								GWT.log(failMsg);
							}
							createClassRootNodeChild(result);
						}
					});
		} else {
			GWT.log("The operation failed!");
			createClassRootNodeChild(null);
		}
	}

	protected void createClassRootNodeChild(EntityData entityData) {
		TreeNode rootChildTreeNode = createTreeNode(entityData);
		if (rootChildTreeNode == null) {
			rootChildTreeNode = new TreeNode("Unknow");
			rootChildTreeNode.setLeaf(true);
			rootChildTreeNode.setExpandable(false);
			rootChildTreeNode.setTooltip("Root node is not defined");
			rootChildTreeNode.setIconCls("protege-deprecated-class-icon");
		} else {
			rootChildTreeNode.setLeaf(false);
			rootChildTreeNode.setExpandable(true);
		}

		getRootNode().appendChild(rootChildTreeNode);

		if (!rootChildTreeNode.isLeaf()) {
			rootChildTreeNode.expand();
		}
	}

	@Override
	protected TreeNode createTreeNode(EntityData entityData) {
		TreeNode node = super.createTreeNode(entityData);
		if (node == null) {
			return node;
		}

		updateNodeIconCls(node, entityData);
		updateNodeText(node, entityData);

		return node;
	}

	protected void updateNodeIconCls(final TreeNode node, EntityData entityData) {
		if (entityData instanceof SubclassEntityData
				&& ((SubclassEntityData) entityData).isDeprecated()) {
			GWTExtUtil
					.setTreeNodeIconCls(node, "protege-deprecated-class-icon");
		} else {
			GWTExtUtil.setTreeNodeIconCls(node, "protege-class-icon");
		}
	}

	protected void updateNodeText(final TreeNode node, EntityData entityData) {
		String text = createNodeText(entityData)
				+ createNodeNoteCount(entityData, node)
				+ createNodeWatchLabel(entityData);

		node.setText(text);
	}

	protected String createNodeText(EntityData entityData) {
		boolean deprecated = false;
		if (entityData instanceof SubclassEntityData) {
			deprecated = ((SubclassEntityData) entityData).isDeprecated();
		}
		if (deprecated) {
			return "<span style=\"opacity: 0.5;\"><del>"
					+ entityData.getBrowserText() + "</del></span>";
		} else {
			return entityData.getBrowserText();
		}
	}

	protected String createNodeNoteCount(EntityData entityData, TreeNode node) {
		String text = "";

		final int localAnnotationsCount = entityData.getLocalAnnotationsCount();
		if (localAnnotationsCount > 0) {
			final String idLocalAnnotationImg = node.getId()
					+ SUFFIX_ID_LOCAL_ANNOTATION_IMG;
			final String idLocalAnnotationCnt = node.getId()
					+ SUFFIX_ID_LOCAL_ANNOTATION_COUNT;

			text = text
					+ "<span style=\"padding-left: 2px;\"><img id=\""
					+ idLocalAnnotationImg
					+ "\" src=\"images/comment-small-filled.png\" title=\""
					+ UIUtil.getNiceNoteCountText(localAnnotationsCount)
					+ " on this category. \nClick on the icon to see and edit the notes\" /></span>"
					+ "<span id=\""
					+ idLocalAnnotationCnt
					+ "\" style=\"font-size:95%;color:#15428B;font-weight:bold;\">"
					+ localAnnotationsCount + "</span>";
		}

		final int childrenAnnotationsCount = entityData
				.getChildrenAnnotationsCount();
		if (childrenAnnotationsCount > 0) {
			text = text
					+ " <span style=\"padding-left: 2px;\"><img src=\"images/comment-small.png\" title=\""
					+ UIUtil.getNiceNoteCountText(childrenAnnotationsCount)
					+ " on the children of this category\" /></span>"
					+ "<span style=\"font-size:90%;color:#999999;\">"
					+ childrenAnnotationsCount + "</span>";
		}

		return text;
	}

	protected String createNodeWatchLabel(EntityData cls) {
		Set<Watch<?>> w = cls.getWatches();
		if (w.isEmpty()) {
			return "";
		}
		if (w.iterator().next() instanceof EntityFrameWatch) {
			return "<img src=\"images/eye.png\" " + WATCH_ICON_STYLE_STRING
					+ " title=\"" + " Watched\"></img>";
		} else {
			return "<img src=\"images/eye-down.png\" "
					+ WATCH_ICON_STYLE_STRING + " title=\""
					+ " Watched branch\"></img>";
		}
	}

	@Override
	protected void getChildren(final TreeNode node) {
		if (node == null || node.getId() == null) {
			return;
		}
		if (node.getChildNodes() != null && node.getChildNodes().length > 0) {
			return;
		}
		if (ROOTNODEID.equals(node.getId())) {
			onRefresh();
			return;
		}
		OntologyServiceManager.getInstance().getSubclasses(
				getProject().getProjectId(), node.getId(),
				new AsyncCallback<List<SubclassEntityData>>() {
					String failMsg = "RPC failure at getting subclasses of "
							+ node.getText();

					@Override
					public void onFailure(Throwable caught) {
						GWT.log(failMsg, caught);
					}

					@Override
					public void onSuccess(List<SubclassEntityData> result) {
						if (result == null || result.size() == 0) {
							GWT.log(failMsg);
						} else {
							for (final SubclassEntityData subclassEntityData : result) {
								final TreeNode childNode = createTreeNode(subclassEntityData);
								if (subclassEntityData.getSubclassCount() > 0) {
									childNode.setLeaf(false);
									childNode.setExpandable(true);
								}
								node.appendChild(childNode);
							}
						}
					}
				});
	}
}
